package cn.edu.szu;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;

public class SignatureUtils {

    // 公钥和私钥
    private BigInteger n, d, e;

    // 创建RSA加密器
    public SignatureUtils(KeyGeneration keyGeneration) {
        // 初始化密钥
        n = keyGeneration.getN();
        e = keyGeneration.getE();
        d = keyGeneration.getD();
    }

    // 根据文件生成数字签名
    public String signature(File origin) {

        byte[] message = null;
        try {
            FileInputStream input = new FileInputStream(origin);
            // 读取文件中所有的字节，进行数字签名
            message = input.readAllBytes();

        } catch (IOException e) {
        }

        // 生成消息摘要
        return signature(message);
    }

    // 使用私钥生成数学签名
    public String signature(byte []message) {
        // 生成消息摘要
        byte[] digest = MD5(message);

        // 加密前的消息摘要
        System.out.println("加密前的消息摘要：" + Arrays.toString(digest));

        byte[] sign = encrypt(digest);

        return Base64.getEncoder().encodeToString(sign);
    }

    // 使用MD5生成消息摘要
    private byte[] MD5 (byte []message) {
        byte[] digest = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            digest = md.digest(message);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return digest;
    }

    // 使用私钥加密消息摘要
    private byte[] encrypt (byte[] message) {

        // 直接将读取到的字节数组转换成BigInteger
        BigInteger plainText = new BigInteger(1, message);

        // 使用私钥加密，得到数字签名
        BigInteger cipherText = plainText.modPow(d, n);

        // 返回加密后的字符串
        return cipherText.toByteArray();
    }

    // 使用公钥解密消息摘要
    public byte[] decrypt (String message) {

        byte[] bytes = Base64.getDecoder().decode(message);

        // 直接将读取到的字节数组转换成BigInteger
        BigInteger cipherText = new BigInteger(1, bytes);

        // 使用公钥解密，得到数字签名
        BigInteger digest = cipherText.modPow(e, n);

        // 待处理的字节数组
        byte []data = digest.toByteArray();

        // 返回完整的字节
        return IntegerUtils.clearBits(data);
    }
}
